﻿/* The tests in this class are adapted from the original Lucandra project.
 * https://github.com/tjake/Lucandra/tree/master/test/lucandra/numericRangeTests.java */

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Lucene.Net.Documents;
using Lucene.Net.Analysis;
using Lucene.Net.Index;
using Lucene.Net.Search;

namespace Lucandra.Net.Tests
{
    [TestClass]
    public class NumericRangeTests
    {
        private static Document first;
        private static Document second;
        private static Document third;
        private static long low;
        private static long mid;
        private static long high;
        private static string indexName;

        static NumericRangeTests()
        {
            indexName = "Test Index";
        }

        [ClassInitialize]
        public static void WriteDocuments(TestContext testContext)
        {
            low = 1277266160637L;
            mid = low + 1000;
            high = mid + 1000;

            first = new Document();
            first.Add(new Field("Id", "first", Field.Store.YES, Field.Index.ANALYZED));


            NumericField numeric = new NumericField("long", Field.Store.YES, true);
            numeric.SetLongValue(low);
            first.Add(numeric);

            second = new Document();
            second.Add(new Field("Id", "second", Field.Store.YES, Field.Index.ANALYZED));

            numeric = new NumericField("long", Field.Store.YES, true);
            numeric.SetLongValue(mid);
            second.Add(numeric);

            third = new Document();
            third.Add(new Field("Id", "third", Field.Store.YES, Field.Index.ANALYZED));

            numeric = new NumericField("long", Field.Store.YES, true);
            numeric.SetLongValue(high);
            third.Add(numeric);

            var writer = new LucandraWriter(indexName);
            //writer.setAutoCommit(false);

            SimpleAnalyzer analyzer = new SimpleAnalyzer();

            writer.AddDocument(first, analyzer);
            writer.AddDocument(second, analyzer);
            writer.AddDocument(third, analyzer);

            //writer.commit();
        }

        [TestMethod]
        public void TestLongRangeInclusive()
        {
            NumericRangeQuery query = NumericRangeQuery.NewLongRange("long",
                 mid, null, true, true);

            var reader = new LucandraReader(indexName);

            LucandraSearcher searcher = new LucandraSearcher(reader);

            TopDocs docs = searcher.Search(query, 1000);

            Assert.AreEqual(2, docs.totalHits);


            var results = new HashSet<String>();

            foreach (ScoreDoc doc in docs.scoreDocs) 
            {
                Document returned = searcher.Doc(doc.doc);
                results.Add(returned.Get("Id"));
            }

            Assert.IsTrue(results.Contains("second"));

            Assert.IsTrue(results.Contains("third"));
        }

        [TestMethod]
        public void TestLongRangeExlusive()
        {
            // now we'll query from the middle inclusive

            NumericRangeQuery query = NumericRangeQuery.NewLongRange("long",
                     mid, null, false, true);

            var reader = new LucandraReader(indexName);

            LucandraSearcher searcher = new LucandraSearcher(reader);

            TopDocs docs = searcher.Search(query, 1000);


            Assert.AreEqual(1, docs.totalHits);

            var results = new HashSet<String>();

            foreach (ScoreDoc doc in docs.scoreDocs) 
            {
                Document returned = searcher.Doc(doc.doc);
                results.Add(returned.Get("Id"));
            }

            Assert.IsTrue(results.Contains("third"));
        }

        [TestMethod]
        public void TestLongRangeLessExclusive()
        {
            // now we'll query from the middle inclusive

            NumericRangeQuery query = NumericRangeQuery.NewLongRange("long",
                     null, mid, true, false);

            var reader = new LucandraReader(indexName);

            LucandraSearcher searcher = new LucandraSearcher(reader);

            TopDocs docs = searcher.Search(query, 1000);

            Assert.AreEqual(1, docs.totalHits);

            var results = new HashSet<String>();

            foreach (ScoreDoc doc in docs.scoreDocs) 
            {
                Document returned = searcher.Doc(doc.doc);
                results.Add(returned.Get("Id"));
            }

            Assert.IsTrue(results.Contains("first"));
        }

        [TestMethod]
        public void TestLongRangeLessInclusive()
        {
            // now we'll query from the middle inclusive

            NumericRangeQuery query = NumericRangeQuery.NewLongRange("long",
                     null, mid, true, true);

            var reader = new LucandraReader(indexName);

            LucandraSearcher searcher = new LucandraSearcher(reader);

            TopDocs docs = searcher.Search(query, 1000);

            Assert.AreEqual(2, docs.totalHits);

            var results = new HashSet<String>();

            foreach (ScoreDoc doc in docs.scoreDocs) 
            {
                Document returned = searcher.Doc(doc.doc);
                results.Add(returned.Get("Id"));
            }

            Assert.IsTrue(results.Contains("first"));
            Assert.IsTrue(results.Contains("second"));
        }

        [TestMethod]
        public void TestLongRangeMinValueAll()
        {
            // now we'll query from the middle inclusive

            NumericRangeQuery query = NumericRangeQuery.NewLongRange("long",
                     long.MinValue, null, true, true);

        
            var reader = new LucandraReader(indexName);

            LucandraSearcher searcher = new LucandraSearcher(reader);

            TopDocs docs = searcher.Search(query, 1000);

            Assert.AreEqual(3, docs.totalHits);

            var results = new HashSet<String>();

            foreach (ScoreDoc doc in docs.scoreDocs) 
            {
                Document returned = searcher.Doc(doc.doc);
                results.Add(returned.Get("Id"));
            }

            Assert.IsTrue(results.Contains("first"));
            Assert.IsTrue(results.Contains("second"));
            Assert.IsTrue(results.Contains("third"));
        }

        [TestMethod]
        public void TestLongRangeMaxAll()
        {
            // now we'll query from the middle inclusive

            NumericRangeQuery query = NumericRangeQuery.NewLongRange("long",
                     null, long.MaxValue, true, true);

            var reader = new LucandraReader(indexName);

            LucandraSearcher searcher = new LucandraSearcher(reader);

            TopDocs docs = searcher.Search(query, 1000);

            Assert.AreEqual(3, docs.totalHits);

            var results = new HashSet<String>();

            foreach (ScoreDoc doc in docs.scoreDocs) 
            {
                Document returned = searcher.Doc(doc.doc);
                results.Add(returned.Get("Id"));
            }

            Assert.IsTrue(results.Contains("first"));
            Assert.IsTrue(results.Contains("second"));
            Assert.IsTrue(results.Contains("third"));
        }

        [TestMethod]
        public void TestLongRangeZeroAll()
        {
             // now we'll query from the middle inclusive

            NumericRangeQuery query = NumericRangeQuery.NewLongRange("long",1L, null, true, true);

            var reader = new LucandraReader(indexName);

            LucandraSearcher searcher = new LucandraSearcher(reader);

            TopDocs docs = searcher.Search(query, 1000);

            Assert.AreEqual(3, docs.totalHits);

            var results = new HashSet<String>();

            foreach (ScoreDoc doc in docs.scoreDocs) 
            {
                Document returned = searcher.Doc(doc.doc);
                results.Add(returned.Get("Id"));
            }

            Assert.IsTrue(results.Contains("first"));
            Assert.IsTrue(results.Contains("second"));
            Assert.IsTrue(results.Contains("third"));
        }

        [ClassCleanup]
        public static void CleanIndexes()
        {
            var writer = new LucandraWriter(indexName);
            writer.DeleteDocuments(new Term("Id", "first"));
            writer.DeleteDocuments(new Term("Id", "second"));
            writer.DeleteDocuments(new Term("Id", "third"));
        }
    }
}
